www.gusucode.com > VC++ 二进制文件浏览编辑器源代码-源码程序 > VC++ 二进制文件浏览编辑器源代码-源码程序\code\HexEditView.cpp
//Download by http://www.NewXing.com //////////////////////////////////////////////////////////////////////////// // File: HexEditView.cpp // Version: 1.0.0.0 // Created: 17-Oct-2003 // // Author: Cuick // E-mail: Cuick@163.net // // You are free to use or modify this code . //////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "二进制编辑.h" #include "HexEditView.h" #include "二进制编辑Doc.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CHexEditView IMPLEMENT_DYNCREATE(CHexEditView, CView) CHexEditView::CHexEditView() { m_text = NULL; } CHexEditView::~CHexEditView() { } BEGIN_MESSAGE_MAP(CHexEditView, CView) //{{AFX_MSG_MAP(CHexEditView) ON_WM_SETFOCUS() ON_WM_KILLFOCUS() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_SIZE() ON_WM_MOUSEWHEEL() ON_WM_HSCROLL() ON_WM_VSCROLL() ON_WM_CHAR() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CHexEditView drawing void CHexEditView::OnDraw(CDC* pDC) { CRect rc; GetClientRect(rc); if(m_text == NULL) { pDC->FillRect(rc, &CBrush(RGB(255,255,255))); return; } CDC dc; dc.CreateCompatibleDC(pDC); CBitmap bm; bm.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height()); dc.SelectObject(bm); dc.SetBoundsRect(&rc, DCB_DISABLE); CFont font; font.CreateFont ( m_LineHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, 0 ); CFont* oldFont = dc.SelectObject ( &font ); CBrush bkBrush(RGB(255,255,255)); dc.FillRect(rc, &bkBrush); UINT lineCY, lineCX; UINT dwPos; char currentchar[20]; UCHAR text[17]; int lineBeginPos; m_HexStart = m_CharWidth * (14 - m_LeftChar); //计算二进制显示开始位置 m_TextStart = m_HexStart + m_CharWidth * 50; //计算ASCII码显示开始位置 for(UINT i = 0; i < m_PageRows; i++) //按行显示数据 { lineBeginPos = (m_TopLine+i-1)*16; //计算当前行开始字符相对于总缓冲区的位置 lineCY = i * m_LineHeight; //当前行的Y坐标 sprintf(currentchar, "%08Xh:", lineBeginPos); dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT)); dc.SetBkColor(RGB(255,255,255)); dc.TextOut (m_CharWidth*(2-m_LeftChar), lineCY, currentchar); //显示地址基值 memcpy(text,&m_text[lineBeginPos],16); //取当前行数据 text[16] = '\0'; for(int l = 0; l < 16; l++) { if(text[l] < 32) text[l] = 46; //不可见ASCII字符用.表示 } if(lineBeginPos+16 > m_CharCount) { text[m_CharCount%16] = '\0'; //最后的数据不满一行时 } dc.TextOut (m_TextStart, lineCY, text);//显示右面的ASCII字符 //被选中时反色显示右面的ASCII字符 int selStart = (m_SelStart - lineBeginPos)<0? 0:(m_SelStart - lineBeginPos); int selEnd = (m_SelEnd - lineBeginPos)>15? 15:(m_SelEnd - lineBeginPos); if(selStart <= 15 && selEnd >= 0) { dc.SetBkColor(::GetSysColor ( COLOR_HIGHLIGHT )); dc.SetTextColor(::GetSysColor ( COLOR_HIGHLIGHTTEXT )); text[selEnd+1]='\0'; dc.TextOut (m_TextStart+selStart*m_CharWidth, lineCY, &text[selStart]); } else { dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT)); dc.SetBkColor(RGB(255,255,255)); } for(UINT j = 0; j < 16; j++) { dwPos = j + lineBeginPos; if(dwPos > (m_CharCount-1)) goto bitblt; //显示完最后一行退出 if(dwPos >= m_SelStart && dwPos <= m_SelEnd) { dc.SetBkColor(::GetSysColor ( COLOR_HIGHLIGHT )); dc.SetTextColor(::GetSysColor ( COLOR_HIGHLIGHTTEXT )); } else { dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT)); dc.SetBkColor(RGB(255,255,255)); } lineCX = m_HexStart + j * m_CharWidth *3 ; //计算当前要显示的二进制字符的位置 sprintf(currentchar, "%02X", ((UCHAR *)m_text)[dwPos]); dc.TextOut (lineCX, lineCY, currentchar); //显示二进制字符 if(dwPos == m_SelEnd) //选中单个字符的显示 { dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT)); dc.SetBkColor(RGB(255,0,0)); UCHAR cHex = m_text[dwPos]; if(m_bFirst)//二进制字符的高四位选中 { cHex = cHex & 0xf0; cHex = cHex >> 4; sprintf(currentchar, "%X", cHex); dc.TextOut (lineCX, lineCY, currentchar); } else { lineCX = m_HexStart + j * m_CharWidth *3 + m_CharWidth; cHex = cHex & 0x0f; sprintf(currentchar, "%X", cHex); dc.TextOut (lineCX, lineCY, currentchar); } } } } bitblt: pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &dc, 0, 0, SRCCOPY); dc.DeleteDC (); } ///////////////////////////////////////////////////////////////////////////// // CHexEditView diagnostics #ifdef _DEBUG void CHexEditView::AssertValid() const { CView::AssertValid(); } void CHexEditView::Dump(CDumpContext& dc) const { CView::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CHexEditView message handlers void CHexEditView::SetText(char *input, int len) { m_text = input; m_CharCount = len; m_Rows = m_CharCount/16; m_TopLine = 1; m_LeftChar = 0; m_SelStart = 0; m_SelEnd = 0; m_StartDrag = FALSE; m_bFirst = TRUE; CFont font; m_LineHeight = 16; font.CreateFont ( m_LineHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, 0 ); CFont* oldFont = GetDC()->SelectObject ( &font ); CSize size = GetDC()->GetTextExtent ("A"); m_LineHeight = size.cy; m_CharWidth = size.cx ; GetPageRowCols(); SetVertScrollBar(); SetHorzScrollBar(); } void CHexEditView::OnSetFocus(CWnd* pOldWnd) { CView::OnSetFocus(pOldWnd); m_bFocused = TRUE; } void CHexEditView::OnKillFocus(CWnd* pNewWnd) { CView::OnKillFocus(pNewWnd); m_bFocused = FALSE; } void CHexEditView::OnLButtonDown(UINT nFlags, CPoint point) { CView::OnLButtonDown(nFlags, point); m_StartDrag = TRUE; m_bFirst = TRUE; m_oriStart = m_SelStart = m_SelEnd = Point2Pos(point); Invalidate(FALSE); } void CHexEditView::OnLButtonUp(UINT nFlags, CPoint point) { CView::OnLButtonUp(nFlags, point); if(m_StartDrag) { m_SelEnd = Point2Pos(point); if(m_SelEnd < m_oriStart) { m_SelStart = m_SelEnd; m_SelEnd = m_oriStart; } else { m_SelStart = m_oriStart; } Invalidate(FALSE); m_StartDrag = FALSE; } } void CHexEditView::OnMouseMove(UINT nFlags, CPoint point) { CView::OnMouseMove(nFlags, point); if(m_StartDrag) { m_SelEnd = Point2Pos(point); if(m_SelEnd < m_oriStart) //反向选择 { m_SelStart = m_SelEnd; m_SelEnd = m_oriStart; } else { m_SelStart = m_oriStart; } Invalidate(FALSE); } } //根据鼠标位置求鼠标当前指向的字符 UINT CHexEditView::Point2Pos(CPoint point) { if(m_text == NULL) return 0; UINT line = m_TopLine + point.y / m_LineHeight - 1;//鼠标所在的行 UINT charset; if(point.x < m_HexStart) charset = 0; else if(point.x < m_HexStart + m_CharWidth * 48) charset = (point.x - m_HexStart)/(m_CharWidth*3); else if(point.x < m_TextStart + 16 * m_CharWidth) charset = (point.x - m_TextStart)/m_CharWidth; else charset = 15; return ((line * 16 + charset)>m_CharCount?m_CharCount-1:(line * 16 + charset)); } void CHexEditView::OnInitialUpdate() { CView::OnInitialUpdate(); } void CHexEditView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); GetPageRowCols(); SetVertScrollBar(); SetHorzScrollBar(); } //设置滚动条 void CHexEditView::SetVertScrollBar() { if((m_Rows - m_TopLine + 2) < m_PageRows) m_TopLine = 1; SCROLLINFO si; ZeroMemory(&si,sizeof(si)); si.cbSize = sizeof(si); si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE; si.nMin = 0; si.nMax = m_Rows; si.nPage = m_PageRows; si.nPos = m_TopLine-1; VERIFY(SetScrollInfo(SB_VERT, &si, TRUE)); Invalidate(FALSE); } void CHexEditView::SetHorzScrollBar() { if((80 - m_LeftChar + 2) < m_PageCols) m_LeftChar = 0; SCROLLINFO si; ZeroMemory(&si,sizeof(si)); si.cbSize = sizeof(si); si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE; si.nMin = 0; si.nMax = 80; si.nPage = m_PageCols; si.nPos = m_LeftChar; VERIFY(SetScrollInfo(SB_HORZ, &si, TRUE)); Invalidate(FALSE); } BOOL CHexEditView::PreCreateWindow(CREATESTRUCT& cs) { CWnd *pParentWnd = CWnd::FromHandlePermanent(cs.hwndParent); if (pParentWnd == NULL || ! pParentWnd->IsKindOf(RUNTIME_CLASS(CSplitterWnd))) { // View must always create its own scrollbars, // if only it's not used within splitter cs.style |= (WS_HSCROLL | WS_VSCROLL); } cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS); return CView::PreCreateWindow(cs); } BOOL CHexEditView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) { if(zDelta > 0) { m_TopLine = --m_TopLine < 1 ? 1 : m_TopLine; } else { if((m_TopLine + m_PageRows -2) < m_Rows) m_TopLine+=1; } SetVertScrollBar(); SetHorzScrollBar(); return CView::OnMouseWheel(nFlags, zDelta, pt); } //计算一页能够显示的字符的行数和列数 void CHexEditView::GetPageRowCols() { CRect rc; GetClientRect(rc); m_PageRows = rc.Height ()/m_LineHeight; m_PageCols = rc.Width ()/m_CharWidth; } //处理滚动条消息 void CHexEditView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { CView::OnHScroll(nSBCode, nPos, pScrollBar); SCROLLINFO si; si.cbSize = sizeof(si); si.fMask = SIF_ALL; VERIFY(GetScrollInfo(SB_HORZ, &si)); switch (nSBCode) { case SB_LEFT: m_LeftChar = 0; break; case SB_BOTTOM: m_LeftChar = 80 - m_PageCols + 1; break; case SB_LINEUP: m_LeftChar = m_LeftChar - 1; break; case SB_LINEDOWN: m_LeftChar = m_LeftChar + 1; break; case SB_PAGEUP: m_LeftChar = m_LeftChar - si.nPage + 1; break; case SB_PAGEDOWN: m_LeftChar = m_LeftChar + si.nPage - 1; break; case SB_THUMBPOSITION: case SB_THUMBTRACK: m_LeftChar = si.nTrackPos; break; default: return; } if((m_LeftChar + m_PageCols - 2) > 80) m_LeftChar = 80 - m_PageCols +2; if(m_LeftChar < 0) m_LeftChar = 0; SetHorzScrollBar(); } void CHexEditView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { CView::OnVScroll(nSBCode, nPos, pScrollBar); SCROLLINFO si; si.cbSize = sizeof(si); si.fMask = SIF_ALL; VERIFY(GetScrollInfo(SB_VERT, &si)); switch (nSBCode) { case SB_TOP: m_TopLine = 0; break; case SB_BOTTOM: m_TopLine = m_Rows - m_PageRows + 1; break; case SB_LINEUP: m_TopLine = m_TopLine - 1; break; case SB_LINEDOWN: m_TopLine = m_TopLine + 1; break; case SB_PAGEUP: m_TopLine = m_TopLine - si.nPage + 1; break; case SB_PAGEDOWN: m_TopLine = m_TopLine + si.nPage - 1; break; case SB_THUMBPOSITION: case SB_THUMBTRACK: m_TopLine = si.nTrackPos+1; break; default: return; } if((m_TopLine + m_PageRows -2) > m_Rows) m_TopLine = m_Rows - m_PageRows + 2; if(m_TopLine < 1) m_TopLine = 1; SetVertScrollBar(); } //输入字符转换成二进制数据 void CHexEditView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { CView::OnChar(nChar, nRepCnt, nFlags); UINT input; UCHAR cHex = m_text[m_SelEnd]; if(nChar > 47 && nChar < 58) { input = nChar - 48; } else if (nChar > 64 && nChar < 71) { input = nChar - 64 + 9; } else if (nChar > 96 && nChar < 103) { input = nChar - 96 + 9; } else { return; } if(m_bFirst) { input = input << 4; cHex = cHex & 0x0f; cHex = cHex | input; m_bFirst = FALSE; m_text[m_SelEnd] = cHex; } else { cHex = cHex & 0xf0; cHex = cHex | input; m_bFirst = TRUE; m_text[m_SelEnd] = cHex; m_SelEnd ++; } if(m_SelEnd == m_CharCount) { m_CharCount = m_SelEnd + 1; m_Rows = m_CharCount/16; } m_text = ((CMyDoc*)GetDocument ())->JudgeMem (m_CharCount + 100); m_SelStart = m_SelEnd; ChangeTop(); ChangeLeft(); Invalidate(FALSE); } //键盘的上下左右键处理 BOOL CHexEditView::PreTranslateMessage(MSG* pMsg) { if(pMsg->message == WM_KEYDOWN) { switch (LOWORD(pMsg->wParam)) { case VK_LEFT: OnCharLeft(); break; case VK_RIGHT: OnCharRight(); break; case VK_UP: OnLineUp(); break; case VK_DOWN: OnLineDown(); break; default: break; } } return CView::PreTranslateMessage(pMsg); } void CHexEditView::OnCharLeft() { if(m_bFirst && m_SelEnd > 0) { m_SelEnd --; m_bFirst = FALSE; } else { m_bFirst = TRUE; } ChangeTop(); ChangeLeft(); m_SelStart = m_SelEnd; Invalidate(FALSE); } void CHexEditView::OnCharRight() { if(m_bFirst) { m_bFirst = FALSE; } else if( m_SelEnd < m_CharCount-1) { m_bFirst = TRUE; m_SelEnd++; } ChangeTop(); ChangeLeft(); m_SelStart = m_SelEnd; Invalidate(FALSE); } void CHexEditView::OnLineUp() { if(m_SelEnd > 15) m_SelEnd = m_SelEnd - 16; ChangeTop(); ChangeLeft(); m_SelStart = m_SelEnd; Invalidate(FALSE); } void CHexEditView::OnLineDown() { if(m_SelEnd + 16 < m_CharCount) m_SelEnd = m_SelEnd + 16; else m_SelEnd = m_CharCount-1; ChangeTop(); ChangeLeft(); m_SelStart = m_SelEnd; Invalidate(FALSE); } //计算顶行 void CHexEditView::ChangeTop() { int newtop = m_TopLine; if((m_SelEnd/16 + 1) < m_TopLine) { newtop = m_SelEnd/16 + 1; } if((m_SelEnd/16 + 2) > m_TopLine+m_PageRows) { newtop = m_SelEnd/16 + 2 - m_PageRows; } if(newtop != m_TopLine) { m_TopLine = newtop; SetVertScrollBar(); } } //计算左列 void CHexEditView::ChangeLeft() { int currentcol = m_SelEnd%16; if(currentcol*3 + 14 < m_LeftChar) { m_LeftChar = currentcol*3 + 14; SetHorzScrollBar(); } if(currentcol*3 + 14 - m_LeftChar+1 > m_PageCols) { m_LeftChar = currentcol*3 + 14 - m_PageCols +2; SetHorzScrollBar(); } }